import { useDebounce, useStore } from '@/hooks';
import { Button, Checkbox, DatePicker2, Grid, Input, Search, Select } from '@alifd/next';
import { ButtonProps } from '@alifd/next/types/button';
import { CheckboxProps, GroupProps } from '@alifd/next/types/checkbox';
import { DatePickerProps, RangePickerProps } from '@alifd/next/types/date-picker2';
import { InputProps, TextAreaProps } from '@alifd/next/types/input';
import { SelectProps } from '@alifd/next/types/select';
import { t } from '@lingui/macro';
import dayjs from 'dayjs';
import { observer } from 'mobx-react-lite';
import React, { useCallback, useEffect, useState } from 'react';
import { BusStationSelect, DictItemSelect, DictTreeSelect } from '../biz';
import ScStationSelect from '../biz/ScStationSelect';
import styles from './index.module.scss';
import CcStationSelect from '../biz/CcStationSelect';

const { Row, Col } = Grid;
const { RangePicker } = DatePicker2;

const RangePreset = {}
RangePreset[t`今天`] = [dayjs(), dayjs()]
RangePreset[t`近一周`] = [dayjs().add(-15, 'day'), dayjs()];
RangePreset[t`本月`] = [dayjs().startOf("month"), dayjs().endOf("month")]

interface IAction extends ButtonProps {
  name: string;
  /**
   * 使用自定义组件
   */
  component?: any;
}

type ItemProps = InputProps | CheckboxProps | GroupProps | TextAreaProps | ButtonProps | SelectProps | DatePickerProps;

interface IDictProps extends SelectProps {
  dictId: string;
}

interface IDictTreeProps extends IDictProps {
  maxLevel: number;
}

interface ISearchItem {
  name: string;
  /**
   * ```
   * input          - 普通输入框
   * checkbox       - 复选框
   * checkbox-group - 复选框组
   * select         - 普通选择框
   * datetime       - 日期选择
   * date-range     - 日期范围选择
   * dict-item      - 字典项下拉选择
   * dict-tree      - 字典项树形选择
   * bus-station    - 巴士站点级联选择
   * cc-station     - 包车站点级联选择
   * sc-station     - 专线站点级联选择
   * ```
   */
  type?: 'input' | 'checkbox' | 'checkbox-group' | 'select' | 'datetime' | 'date-range' | 'dict-item' | 'dict-tree' | 'bus-station' | 'cc-station' | 'sc-station';
  value: any;
  /**
   * 组件属性。不要指定onChange，如指定则需要自行处理参数值
   */
  props: ItemProps;
  /**
   * 使用自定义组件时，指定组件类名称，必须具备onChange(value: string)方法
   * 此时type属性被忽略
   */
  component?: any;
  onChange?: (value: string) => void;
}

interface IExtraItem {
  name: string;
  /**
   * 使用自定义组件
   */
  component?: any;
}

const defaultKeywordSearch: IKeywordSearch = {
  enabled: true,
}

interface IKeywordSearch {
  enabled: boolean;
  placeholder?: string;
  value?: string;
  onSearch?: (value: string) => void;
  onChange?: (value: string) => void;
}

type IOnSearch = (params: { values: any, valueObjects: any }) => void;

interface IActionPanelProps extends React.HTMLAttributes<HTMLElement> {
  /**
   * 参数变化时的回调
   */
  onSearch?: IOnSearch; //(params: { values: any, valueObjects: any }) => void;
  /**
   * 动作按钮列表
   */
  actions?: IAction[];
  /**
   * 搜索参数条目列表
   */
  searchItems?: ISearchItem[];
  /**
   * 其他扩展组件
   */
  extraItems?: IExtraItem[];
  /**
   * 关键字搜索配置
   */
  keywordSearch?: IKeywordSearch;
  /**
   * 默认值
   */
  defaultValues?: any;
}

/**
 * 使用示例：
 * ```js
  actions={[
    {
      title: t`人工下单`,
      type: 'primary',
      onClick: () => setModal('placeOrder'),
    },
    {
      name: 'btn-syncStatus',
      title: t`同步最近状态`,
      type: 'primary',
      onClick: async () => {
        await store.sync();
        Message.success({ content: t`同步成功` });
      },
    },
  ]}
  searchItems = {[
    { // 自定义组件
      name: 'text',
      component: Input,
      props: {
        placeholder: t`随便什么文字`,
      },
    },
    { // 输入框
      name: 'text2',
      type: 'input',
      props: {
        placeholder: t`随便什么文字2`,
      },
    },
    { // 日期选择
      name: 'crDate',
      type: 'datetime',
      props: {
        placeholder: t`订单创建时间`,
      },
    },
    { // 字典tree级联选择
      name: 'district',
      type: 'dict-tree',
      props: { placeholder: t`行政区`, dictId: 'region', maxLevel: 2 },
    },
    { // 字典项下拉列表
      name: 'gender',
      type: 'dict-item',
      props: { placeholder: t`性别`, dictId: 'gender' },
    },
    {
      name: 'orderDate',
      type: 'date-range',
      props: {
        placeholder: [t`起始订单时间`, t`结束订单时间`],
      },
    },
    {
      name: 'ticketState',
      type: 'select',
      props: {
        dataSource: toSelectDataSource(ENUMS.ticketStatus),
        placeholder: t`车票状态`,
      },
    },
    {
      name: 'isRoundTrip',
      type: 'select',
      props: {
        dataSource: toSelectDataSource(ENUMS.roundTrip),
        placeholder: t`单双程`,
      },
    },
    {
      name: 'getOnDate',
      type: 'date-range',
      props: {
        placeholder: [t`起始上车时间`, t`结束上车时间`],
      },
    },
    {
      name: 'startStations',
      type: ' bus-station',
      props: { placeholder: t`始发站点`, changeOnSelect: true, style: { minWidth: '160px' } },
    },
    {
      name: 'endStations',
      type: 'bus-station',
      props: { placeholder: t`结束站点`, changeOnSelect: true, style: { minWidth: '160px' } },
    },
  ]}

 * ```
 *
 * @param param0
 * @returns
 */
const TauActionPanel: React.FunctionComponent<IActionPanelProps> = ({
  onSearch,
  actions = [],
  searchItems = [],
  extraItems = [],
  // keywordSearch = {} as IKeywordSearch,
  defaultValues,
  ...props }) => {
  const [params, setParams] = useState({
    values: defaultValues || {} as any,
    valueObjects: {},
  });

  const { ruleStore } = useStore();

  const keywordSearch = Object.assign({}, defaultKeywordSearch, props.keywordSearch);

  // 定义debounce操作，注意回调函数也需啊作为参数传递
  const debounceFetch = useDebounce((p: any, cb: IOnSearch) => { cb?.(p); });

  // 响应onSearch改变调整回调函数的实例，以便在onSearch中使用的状态值能及时更新。此时onSearch的声明最好使用userCallback包装
  const onFetch = useCallback((p: any) => { onSearch?.(p); }, [onSearch]);

  // 清理debounceFetch
  useEffect(() => () => debounceFetch.cancel(), [debounceFetch]);

  // params变化时执行防抖包装的查询操作
  useEffect(() => { debounceFetch(params, onFetch); }, [params]);

  const handleChange = (item, v, obj?) => {
    item.onChange && item.onChange(v);
    setParams((prev) => {
      prev.values[item.name] = v;
      prev.valueObjects[item.name] = obj || v;
      return { ...prev };
    });
  };

  const handleReset = () => {
    setParams({ values: {}, valueObjects: {} });
    // onSearch?.(emptyParams);
  }


  const renderAction = (item: IAction) => {
    if (item.component) {
      return item.component;
    }
    const { name, title, onClick, ...other } = item;
    return (
      <Button key={name} onClick={onClick} {...other}>
        {title}
      </Button>
    );

  };

  const renderItem = (item: ISearchItem) => {
    if (item.component) {
      return <item.component key={item.name} value={params.values[item.name]} hasClear {...item.props} onChange={(v, _, obj) => handleChange(item, v, obj)} />;
    }
    switch (item.type) {
      case 'checkbox':
        return <Checkbox key={item.name} value={params.values[item.name]} style={{ marginLeft: 10, ...(ruleStore._isPhone ? { width: '100%' } : {}) }} {...(item.props as CheckboxProps)} onChange={(v) => handleChange(item, v)} />;
      case 'checkbox-group':
        return <Checkbox.Group key={item.name} value={params.values[item.name]} style={{ marginLeft: 10, ...(ruleStore._isPhone ? { width: '100%' } : {}) }} {...(item.props as GroupProps)} onChange={(v) => handleChange(item, v)} />;
      case 'datetime':
        return <DatePicker2 key={item.name} value={params.values[item.name]} style={{ ...(ruleStore._isPhone ? { width: '100%' } : {}) }} {...(item.props as DatePickerProps)} onChange={(v) => handleChange(item, v && v.format('YYYY-MM-DD'))} />;
      case 'date-range':
        return <RangePicker key={item.name} value={params.values[item.name]} style={{ ...(ruleStore._isPhone ? { width: '100%' } : {}) }} preset={RangePreset} {...(item.props as RangePickerProps)} onChange={(v) => handleChange(item, v.map(d => d && d.format('YYYY-MM-DD')))} />;
      case 'select':
        return <Select key={item.name} hasClear value={params.values[item.name]} style={{ ...(ruleStore._isPhone ? { width: '100%' } : {}) }} {...(item.props as SelectProps)} onChange={(v, _, obj) => handleChange(item, v, obj)} />;
      case 'dict-item':
        return <DictItemSelect key={item.name} value={params.values[item.name]} style={{ ...(ruleStore._isPhone ? { width: '100%' } : {}) }} dictId={(item.props as IDictProps).dictId} {...item.props} onChange={(v, _, obj) => handleChange(item, v, obj)} />
      case 'dict-tree':
        return <DictTreeSelect key={item.name} value={params.values[item.name]} dictId={(item.props as IDictTreeProps).dictId} {...item.props} onChange={(v, _, obj) => handleChange(item, v, obj)} />
      case 'bus-station':
        return <BusStationSelect key={item.name} value={params.values[item.name]} {...item.props} onChange={(v, _, obj) => {
          handleChange(item, v, obj)
        }} />
      case 'sc-station':
        return <ScStationSelect key={item.name} value={params.values[item.name]} hasClear {...item.props} onChange={(v, _, obj) => handleChange(item, v, obj)} />
      case 'cc-station':
        return <CcStationSelect key={item.name} value={params.values[item.name]} hasClear {...item.props} onChange={(v, _, obj) => handleChange(item, v, obj)} />
      default:
        return <Input key={item.name} value={params.values[item.name]} hasClear composition {...(item.props as InputProps)} onChange={(v) => handleChange(item, v)} />;
    }

  }

  const renderExtra = (item: IExtraItem) => {
    return item.component;
  }

  return (
    <div className={`${styles.actionPanel} ${props.className}`}>
      <Row style={{ columnGap: 4 }}>
        <Col span={keywordSearch.enabled ? 19 : 24} style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center', rowGap: 6, columnGap: 4 }}>
          {actions.map((item) => renderAction(item))}
          <Search
            style={{ width: '100%', display: !ruleStore._isPhone ? 'none' : '' }}
            hasClear
            shape="simple"
            placeholder={keywordSearch.placeholder}
            value={params.values.keyword || keywordSearch.value}
            onChange={(v) => handleChange({ name: 'keyword' }, v)}
            onSearch={() => onSearch?.(params)}
          />
          {searchItems.map((item) => renderItem(item))}
          {searchItems.length > 1 && <Button onClick={handleReset}>{t`重置`}</Button>}
          {extraItems.map((item) => renderExtra(item))}
        </Col>
        {(keywordSearch.enabled && !ruleStore._isPhone) &&
          <Col span={5} >
            <Search
              style={{ width: '100%', marginRight: -1 }}
              hasClear
              shape="simple"
              placeholder={keywordSearch.placeholder}
              value={params.values.keyword || keywordSearch.value}
              onChange={(v) => handleChange({ name: 'keyword' }, v)}
              onSearch={() => onSearch?.(params)}
            />
            {/* <Balloon.Tooltip v2 trigger={<Button onClick={() => setParams({ values: {}, valueObjects:{}})}><Icon type="close" /></Button>} triggerType="hover">
              {t`重置`}
            </Balloon.Tooltip> */}
          </Col>}
      </Row>
    </div>
  );
}

export default observer(TauActionPanel);
